/*============================================================================
 *
 *      emv_loopback.c
 *
 *      
 *
 *==========================================================================*/
/*============================================================================
 * 
 * Copyright (c) 2002-2010 Maxim Integrated Products.
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Maxim Integrated Products ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered
 * into with Maxim Integrated Products.
 *
 * Maxim Integrated Products makes no representations or warranties about the suitability of 
 * the software, either express or implied, including but not limited to 
 * the implied warranties of merchantability, fitness for a particular purpose, 
 * or non-infrigement. Maxim Integrated Products shall not be liable for any damages suffered 
 * by licensee as the result of using, modifying or distributing this software 
 * or its derivatives.
 * 
 *==========================================================================*/
/*============================================================================
 * 
 * Author(s): Maxim Integrated Products
 * Contributors:
 * Date:          
 * Purpose:       
 * Description:
 * 
 *==========================================================================*/

/** Global includes */
#include <config.h>
#include <errors.h>
/** Other includes */
#include <cobra_defines.h>
#include <cobra_macros.h>
#include <cobra_functions.h>
#include <mml_sc.h>
#include <mml_sc_dev.h>
#include <mml_sc_regs.h>
/** Local includes */
#include <libemv.h>
#include <emv_loopback.h>
#include <printf_lite.h>




const unsigned char emv_select_file_cmd[] = {0x00, 0xA4, 0x04, 0x00};
const unsigned char emv_select_file_aid[]="1PAY.SYS.DDF01" ;

#define LOOPBACK_PATH_TIME_EXTENDED_MASTERCARD_Y
#ifdef _WITH_EMV_LOOPBACK_
/******************************************************************************/
int emv_loopback( void )
{
    int											result = COMMON_ERR_UNKNOWN;
    unsigned int								len = 64;
    unsigned char								atr[64];
    apdu_buf_t									c_apdu;
    apdu_buf_t									r_apdu;

    /** Smart card power on */
    result = emv_power_up(atr, &len);
    if ( result == NO_ERROR )
    {
        /** Prepare the first APDU (emv_select_file_cmd Visa Credit) */
        emv_prepare_select_file(&c_apdu, &r_apdu);
        while( 1 )
        {
        	/** For bug INTEGRI test tools */
            delay_micro(100); //HA debug EMV
#ifdef LOOPBACK_PATH_TIME_EXTENDED_MASTERCARD_Y
            //HA debug EMV
           	delay_micro(600000);  //wait 200 ms approximative for compliant loopback patched for Master Card
#endif
            result = emv_transmit(c_apdu.data,
            						c_apdu.length,
            						r_apdu.data,
            						&r_apdu.length);

            if ( ( result != NO_ERROR ) &&
            	( result != N_SCS_ERR_CMD_ABORTED ) )
			{
     	           	break;
			}
            /** Prepare next APDU */
            if ( r_apdu.length < 6 )
                /** Default APDU Command = select PSE */
                emv_prepare_select_file(&c_apdu, &r_apdu);
            else if( 0x70 == r_apdu.data[1])
                /** Abort loopback */
                break;
            else
            {
                /** Loopback */
                c_apdu.length = r_apdu.length - 2;
                /** CLA/INS/P1 */
                memcpy(c_apdu.data , r_apdu.data, c_apdu.length);
                r_apdu.length = APDU_BUFFER_MAX_SIZE;
            }
        }
    }
    /** Smart card power down */
    result = emv_power_down();
    /** We're done */
    return result;
}
#else
/******************************************************************************/
int emv_test(void)
{
    int											result = COMMON_ERR_UNKNOWN;
    unsigned int								len = 64;
    unsigned int								i;
    unsigned char								atr[64];
    apdu_buf_t									c_apdu;
    apdu_buf_t									r_apdu;
   
    /** Smart card power on */
    result = emv_power_up(atr, &len);
    if ( result == NO_ERROR )
    {
				lite_printf("\nSmart card is powered up. ATR:\n");
				
				/** Dump out the ATR */
				for (i=0; i<len; i++)
				{
						lite_printf("%X", atr[i]);
				}
				
				lite_printf("\n");
				
        /** Prepare the first APDU (emv_select_file_cmd Visa Credit) */
        emv_prepare_select_file(&c_apdu, &r_apdu); 
        /** for bug INTEGRI test tools */
        delay_micro(10);
		result = emv_transmit(c_apdu.data, c_apdu.length, r_apdu.data, &r_apdu.length);
		if ( ( NO_ERROR != result ) && ( N_SCS_ERR_CMD_ABORTED != result ) )
		{
			lite_printf("\nEMV Transmit failed\n");
			goto emv_test_out;
		}
		else
		{
			lite_printf("Return APDU is :");
			for( i = 0 ; i < r_apdu.length;i++ )
			{
				lite_printf("0x%2x ", r_apdu.data[i]);
			}
		}
    } else
    {
    	lite_printf("Smart card power up failed\n");
    	goto emv_test_out;
    }
    /** Smart card power down */
    result = emv_power_down();
    lite_printf("\nSmart card is powered down.\n");
    /** We're done */
emv_test_out:
    return result;
}
#endif /* _WITH_EMV_LOOPBACK_ */

/******************************************************************************/
void emv_prepare_select_file(apdu_buf_t *c_apdu, apdu_buf_t *r_apdu )
{ 
    /** Prepare APDU header */
    memcpy(c_apdu->data, emv_select_file_cmd, 4);
    c_apdu->data[Lc_OFFSET] = EMV_SELECT_FILE_LEN;
    /** Prepare APDU data */
    memcpy(&c_apdu->data[5], emv_select_file_aid, EMV_SELECT_FILE_LEN);
    /** Set Le */
    c_apdu->data[5 + EMV_SELECT_FILE_LEN] = 0;
    c_apdu->length = 6 + EMV_SELECT_FILE_LEN;
    /** Prepare APDU response */
    r_apdu->length = APDU_BUFFER_MAX_SIZE;
    /** We're done */
    return;
}

/******************************************************************************/
/* EOF */
